// A/B测试框架

const crypto = require('crypto');
const { logger } = require('../../../config/monitoring');

class ABTestManager {
  constructor() {
    this.experiments = new Map();
    this.loadExperiments();
  }

  // 加载实验配置
  loadExperiments() {
    // 从配置文件或数据库加载实验
    const experiments = [
      {
        id: 'new_ad_reward_system',
        name: '新广告奖励系统',
        description: '测试新的广告奖励算法',
        status: 'active',
        startDate: new Date('2024-01-01'),
        endDate: new Date('2024-12-31'),
        trafficAllocation: 50, // 50%的用户参与实验
        variants: [
          {
            id: 'control',
            name: '对照组',
            allocation: 50, // 50%
            config: {
              adRewardMultiplier: 1.0
            }
          },
          {
            id: 'treatment',
            name: '实验组',
            allocation: 50, // 50%
            config: {
              adRewardMultiplier: 1.2
            }
          }
        ],
        metrics: ['ad_completion_rate', 'user_retention', 'points_earned'],
        targetAudience: {
          newUsers: true,
          regions: ['beijing', 'shanghai'],
          minVersion: '1.0.0'
        }
      },
      
      {
        id: 'new_ui_design',
        name: '新UI设计',
        description: '测试新的用户界面设计',
        status: 'active',
        startDate: new Date('2024-01-01'),
        endDate: new Date('2024-06-30'),
        trafficAllocation: 30,
        variants: [
          {
            id: 'control',
            name: '原版UI',
            allocation: 70,
            config: {
              uiVersion: 'v1'
            }
          },
          {
            id: 'treatment',
            name: '新版UI',
            allocation: 30,
            config: {
              uiVersion: 'v2'
            }
          }
        ],
        metrics: ['click_through_rate', 'user_engagement', 'conversion_rate'],
        targetAudience: {
          newUsers: false,
          regions: [],
          minVersion: '1.1.0'
        }
      }
    ];

    experiments.forEach(exp => {
      this.experiments.set(exp.id, exp);
    });

    logger.info('AB experiments loaded', { count: this.experiments.size });
  }

  // 获取用户的实验分组
  getUserVariant(experimentId, userId, userInfo = {}) {
    const experiment = this.experiments.get(experimentId);
    
    if (!experiment || experiment.status !== 'active') {
      return null;
    }

    // 检查实验时间范围
    const now = new Date();
    if (now < experiment.startDate || now > experiment.endDate) {
      return null;
    }

    // 检查目标受众
    if (!this.isTargetUser(experiment, userInfo)) {
      return null;
    }

    // 检查是否参与实验
    const participationHash = crypto.createHash('md5')
      .update(`${experimentId}_participation_${userId}`)
      .digest('hex');
    const participationValue = parseInt(participationHash.substring(0, 8), 16) % 100;
    
    if (participationValue >= experiment.trafficAllocation) {
      return null; // 不参与实验
    }

    // 确定分组
    const variantHash = crypto.createHash('md5')
      .update(`${experimentId}_variant_${userId}`)
      .digest('hex');
    const variantValue = parseInt(variantHash.substring(0, 8), 16) % 100;
    
    let cumulativeAllocation = 0;
    for (const variant of experiment.variants) {
      cumulativeAllocation += variant.allocation;
      if (variantValue < cumulativeAllocation) {
        return {
          experimentId,
          variantId: variant.id,
          variantName: variant.name,
          config: variant.config
        };
      }
    }

    // 默认返回对照组
    return {
      experimentId,
      variantId: experiment.variants[0].id,
      variantName: experiment.variants[0].name,
      config: experiment.variants[0].config
    };
  }

  // 检查是否为目标用户
  isTargetUser(experiment, userInfo) {
    const { targetAudience } = experiment;
    
    // 检查新用户条件
    if (targetAudience.newUsers !== undefined) {
      const isNewUser = userInfo.isNewUser || false;
      if (targetAudience.newUsers !== isNewUser) {
        return false;
      }
    }

    // 检查地区条件
    if (targetAudience.regions && targetAudience.regions.length > 0) {
      const userRegion = userInfo.region || '';
      if (!targetAudience.regions.includes(userRegion)) {
        return false;
      }
    }

    // 检查版本条件
    if (targetAudience.minVersion) {
      const userVersion = userInfo.version || '1.0.0';
      if (this.compareVersions(userVersion, targetAudience.minVersion) < 0) {
        return false;
      }
    }

    return true;
  }

  // 版本比较
  compareVersions(version1, version2) {
    const v1Parts = version1.split('.').map(Number);
    const v2Parts = version2.split('.').map(Number);
    
    for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
      const v1Part = v1Parts[i] || 0;
      const v2Part = v2Parts[i] || 0;
      
      if (v1Part > v2Part) return 1;
      if (v1Part < v2Part) return -1;
    }
    
    return 0;
  }

  // 记录实验事件
  async recordEvent(userId, experimentId, variantId, eventType, eventData = {}) {
    try {
      const eventRecord = {
        userId,
        experimentId,
        variantId,
        eventType,
        eventData,
        timestamp: new Date()
      };

      // 保存到数据库
      // await ABTestEvent.create(eventRecord);

      logger.info('AB test event recorded', eventRecord);
    } catch (error) {
      logger.error('Failed to record AB test event:', error);
    }
  }

  // 获取实验结果
  async getExperimentResults(experimentId) {
    try {
      const experiment = this.experiments.get(experimentId);
      if (!experiment) {
        throw new Error('Experiment not found');
      }

      // 从数据库查询实验数据
      // const events = await ABTestEvent.findAll({
      //   where: { experimentId },
      //   attributes: [
      //     'variantId',
      //     'eventType',
      //     [sequelize.fn('COUNT', sequelize.col('id')), 'count'],
      //     [sequelize.fn('COUNT', sequelize.fn('DISTINCT', sequelize.col('userId'))), 'uniqueUsers']
      //   ],
      //   group: ['variantId', 'eventType']
      // });

      // 模拟结果数据
      const results = {
        experimentId,
        experimentName: experiment.name,
        status: experiment.status,
        startDate: experiment.startDate,
        endDate: experiment.endDate,
        variants: experiment.variants.map(variant => ({
          id: variant.id,
          name: variant.name,
          allocation: variant.allocation,
          participants: 0,
          metrics: {}
        })),
        summary: {
          totalParticipants: 0,
          statisticalSignificance: false,
          winningVariant: null,
          confidenceLevel: 0
        }
      };

      return results;
    } catch (error) {
      logger.error('Failed to get experiment results:', error);
      throw error;
    }
  }

  // 获取所有活跃实验
  getActiveExperiments() {
    const activeExperiments = [];
    const now = new Date();

    for (const [id, experiment] of this.experiments) {
      if (experiment.status === 'active' && 
          now >= experiment.startDate && 
          now <= experiment.endDate) {
        activeExperiments.push({
          id,
          name: experiment.name,
          description: experiment.description,
          trafficAllocation: experiment.trafficAllocation,
          variants: experiment.variants.length
        });
      }
    }

    return activeExperiments;
  }

  // 停止实验
  async stopExperiment(experimentId, reason = '') {
    try {
      const experiment = this.experiments.get(experimentId);
      if (!experiment) {
        throw new Error('Experiment not found');
      }

      experiment.status = 'stopped';
      experiment.endDate = new Date();
      experiment.stopReason = reason;

      // 更新数据库
      // await ABTestExperiment.update(
      //   { status: 'stopped', endDate: new Date(), stopReason: reason },
      //   { where: { id: experimentId } }
      // );

      logger.info('AB test experiment stopped', { experimentId, reason });
    } catch (error) {
      logger.error('Failed to stop experiment:', error);
      throw error;
    }
  }
}

// 创建全局实例
const abTestManager = new ABTestManager();

// A/B测试中间件
const abTestMiddleware = (req, res, next) => {
  req.abTest = {
    getUserVariant: (experimentId, userId, userInfo) => 
      abTestManager.getUserVariant(experimentId, userId, userInfo),
    recordEvent: (userId, experimentId, variantId, eventType, eventData) =>
      abTestManager.recordEvent(userId, experimentId, variantId, eventType, eventData),
    getActiveExperiments: () => abTestManager.getActiveExperiments()
  };

  next();
};

module.exports = {
  abTestManager,
  abTestMiddleware
};